﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using log4net;
using log4net.Repository;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json.Linq;
using QQZiFramework.Membership;
using Microsoft.Extensions.Hosting;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.VisualBasic;
using System.Net.Http;
using Microsoft.AspNetCore.Routing;

namespace QQZiFramework.Mvc
{
    public abstract class WebHostMemberShip : CommonMemberShip
    {
        public const string DBCONTEXT_NAME_IN_HTTP_CONTEXT = "qqzi-context";

        public WebHostMemberShip()
        {

        }

        public System.Net.WebSockets.ClientWebSocket SocketClient { get; set; }

        private static Dictionary<string, QueryEntityConfig> queryMapping;

        /// <summary>
        /// Permission文件的内容
        /// </summary>  
        public override Dictionary<string, QueryEntityConfig> GetPermissionQueryMapping(DBContext context)
        {
            if (queryMapping != null) return queryMapping;
            string filePath = Path.Combine(QQZiFramework.Mvc.Extension.GetAppRootPath(), "Permission.json");
            string json = Utility.ReadFile(filePath);
            if (string.IsNullOrEmpty(json)) queryMapping = new Dictionary<string, QueryEntityConfig>();
            else queryMapping = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, QueryEntityConfig>>(json);
            return queryMapping;
        }

        public override string MessageAsyncPath
        {
            get { return "Public/TriggerMessageSent"; }
        }

        public string GetConfigValue(string path)
        {
            if (path == "path") throw new Exception("不允许使用path");
            return Extension.Configuration[path];
        }

        public bool TryGetConfigValue<T>(string path, out T t)
        {
            if (path == "path") throw new Exception("不允许使用path");
            Type type = typeof(T);
            if (type != typeof(string) && type.IsClass)
            {
                IConfigurationSection section = Extension.Configuration.GetSection(path);
                bool HasValues = false;
                if (section != null)
                {
                    t = (T)System.Activator.CreateInstance(typeof(T));
                    foreach (var item in typeof(T).GetProperties())
                    {
                        string str = section[item.Name];
                        if (str != null)
                        {
                            HasValues = true;
                            object obj = Convert.ChangeType(str, item.PropertyType);
                            item.SetValue(t, obj);
                        }
                    }
                    if (!HasValues)
                    {
                        t = default(T);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    t = default(T);
                    return false;
                }

            }
            else
            {
                string str = Extension.Configuration[path];
                if (str == null)
                {
                    t = default(T);
                    return false;
                }
                t = (T)Convert.ChangeType(str, typeof(T));
            }
            return true;
        }

        public static string MapPath(string path)
        {
            return Extension.MapPath(path);
        }

        public virtual string GetNacosUrl(string nacosServiceName, DBContext mainContext){
            throw new Exception("需要配置nacos使用！");
        }

        public override BaseUser GetRedisUser(int userId, DBContext context)
        {
            if (!DBContext.UserRedis) throw new Exception("需要配置redis使用！");
            string key = "User_" + userId;
            int dbIndex = GetLoginStateDBIndex(context);
            string userJson = context.GetRedisDatabase(dbIndex).GetRedisItem<string>(key, false);
            // User u = context.GetRedisItem<User>(key, false);
            IDBEntity user;
            if (userJson == null)
            {
                QueryParam param = new QueryParam() { entityType = UserType };
                param.AddWhere("UserId", userId.ToString());
                user = context.DoGetOne(param, "找不到用户" + userId);
                context.SetRedisItem(key, userJson);
            }
            else user = (IDBEntity)Newtonsoft.Json.JsonConvert.DeserializeObject(userJson, UserType);
            return user as BaseUser;
        }

       

        /// <summary>
        /// 是否以传token方式访问（比如App）
        /// </summary>
        /// <returns></returns>
        public bool IsTokenMode(DBContext context)
        {
            return GetRequestToken(context) != null;
        }

        /// <summary>
        /// 不记日志的DBContext，用来获取登录用户信息
        /// </summary>
        protected static DBContext NoLogDbContext = new DBContext() { LogSql = SqlLogMode.NoLog };

        public static string GetPathAndQuery(HttpRequest request)
        {
            return request.Path + request.QueryString;
        }

        public virtual string GetUrlForMd5Check(ControllerBase controller)
        {
            string url = WebHostMemberShip.GetPathAndQuery(controller.HttpContext.Request);
            int pos = url.IndexOf("secret=");
            url = url.Substring(0, pos - 1);
            if (controller.RouteData.Values.ContainsKey("area"))
            {
                string areaName = controller.RouteData.Values["area"].ToString();
                pos = url.IndexOf(areaName, StringComparison.OrdinalIgnoreCase);//地址中有包括area
                if (pos > -1 && pos < 5)
                {
                    url = url.Substring(areaName.Length + 1);//截取前面的区域，比如/Admin
                }
            }
            return url;
        }

        /// <summary>
        /// 获取客户端IP地址
        /// </summary>
        /// <returns></returns>
        public static string GetWebClientIp(HttpRequest request)
        {
            String clientIP = request.HttpContext.Connection.RemoteIpAddress.ToString();
            if (!string.IsNullOrEmpty(clientIP)) return clientIP;
            clientIP = request.Headers["HTTP_X_FORWARDED_FOR"];
            if (string.IsNullOrEmpty(clientIP) || (clientIP.ToLower() == "unknown"))
            {
                clientIP = request.Headers["HTTP_X_REAL_IP"];
                if (string.IsNullOrEmpty(clientIP))
                {
                    clientIP = request.Headers["REMOTE_ADDR"];
                }
            }
            else
            {
                clientIP = clientIP.Split(',')[0];
            }

            return clientIP;
        }

        public static void ReloadConfig()
        {
            queryMapping = null;
        }

        public static Newtonsoft.Json.Linq.JToken GetPostJson(IQQZiController controller)
        {
            if (!controller.IsApplicationJson) return null;
            DBContext context = controller.CreateDBContext();
            Newtonsoft.Json.Linq.JToken _postJson = context.GetArgument<Newtonsoft.Json.Linq.JToken>("_post_json");
            if (_postJson != null) return _postJson;
            HttpContext Http = controller.HttpContext;
            string json = GetRequestBodyString(controller);
            Http.Request.Body.Position = 0;
            if (json == "" || json[0] != '{') json = "{}";
            else
            {
                if (json.Length > 8)
                {
                    MatchCollection ms = Regex.Matches(json, "\\\"[a-zA-Z0-9_]+\\\"\\s*:");
                    if (ms == null || ms.Count == 0) throw new Exception("json参数名请添加引号");
                    foreach (Match item in ms)
                    {
                        json = json.Replace(item.Value, item.Value.ToUpper());
                    }
                }
            }
            _postJson = Newtonsoft.Json.Linq.JToken.Parse(json);
            context.SetArgument("_post_json", _postJson);
            return _postJson;

        }

        public static string GetPostJsonParamVal(IQQZiController controller, string name)
        {
            Newtonsoft.Json.Linq.JToken token = GetPostJson(controller);
            if (token == null) return null;
            return token.Value<string>(name.ToUpper());
        }




        public static string GetRequestBodyString(IQQZiController controller)
        {
            DBContext context = controller.CreateDBContext();
            string body = context.GetArgument<string>("_http_body");
            if (body != null) return body;
            var reader = new StreamReader(controller.HttpContext.Request.Body, encoding: Encoding.UTF8);
            body = reader.ReadToEndAsync().Result;
            context.SetArgument("_http_body", body);
            controller.HttpContext.Request.Body.Position = 0;
            return body;

        }

        public static string GetFormString(IQQZiController controller)
        {
            HttpRequest request = controller.HttpContext.Request;
            if (controller.IsApplicationJson)
            {
                return GetRequestBodyString(controller);
            }
            else
            {
                if (!request.HasFormContentType) return null;
                StringBuilder formData = new StringBuilder();
                if (request.ContentLength > 0)
                {
                    formData.Append("{");
                    foreach (string key in request.Form.Keys)
                    {
                        formData.Append("\"");
                        formData.Append(key);
                        formData.Append("\":\"");
                        string formVal = request.Form[key].ToString();
                        if (formVal != null) formData.Append(formVal.Length > 1024 ? "长内容" : formVal);
                        formData.Append("\",");
                    }
                    formData.Remove(formData.Length - 1, 1);
                    formData.Append("}");

                }
                return formData.ToString();
            }

        }

        // public static void SetWeiXinUser(DBContext context, string openid, OAuthUser oAuthUser_Model)
        // {
        //     context.SetRedisItem(openid, oAuthUser_Model);
        //     context.SetSession("openId", openid);
        // }

        // public static OAuthUser GetWeiXinUser(IQQZiController controller)
        // {
        //     DBContext context = controller.CreateDBContext();
        //     OAuthUser wxUser = null;
        //     string openId = controller.HttpContext.Request.Headers["WX-OpenID"];
        //     if (openId == null) openId = context.GetArgument<string>("openId");
        //     if (openId == null) openId = context.GetSession<string>("openId");
        //     if (openId != null)
        //     {
        //         wxUser = context.GetRedisItem<OAuthUser>(openId, false);
        //     }
        //     return wxUser;

        // }

        public virtual void OnActionExecuting(DBContext context, ActionExecutingContext filterContext, string Alias)
        {
            HttpRequest request = filterContext.HttpContext.Request;
            string requestContent = null;
            string ip = GetWebClientIp(request);
            string pathAndQuery = GetPathAndQuery(request);
            string logActionName = Alias;
            if (logActionName == null)
            {
                ControllerActionDescriptor ActionDescriptor = (ControllerActionDescriptor)filterContext.ActionDescriptor;
                logActionName = ActionDescriptor.ControllerName + '-' + ActionDescriptor.ActionName;
            }
            if (request.ContentLength != null && request.ContentLength > 0 && request.HasFormContentType && request.Form.Files.Count > 0)
            {
                context.LogMessage("上传文件" + request.Form.Files[0].FileName, "执行");
            }
            else
            {
                if (request.ContentLength != null && request.ContentLength > 0 && request.HasFormContentType && request.Form.ContainsKey("base64Str"))
                {
                    context.LogMessage("上传文件", "执行");
                }
                else
                {
                    requestContent = WebHostMemberShip.GetFormString((IQQZiController)filterContext.Controller);
                    context.LogMessage(request.Headers["User-Agent"] + "，" + ip + "，" + pathAndQuery + "，" + requestContent, logActionName);
                }
            }
            LoginCheckFilterAttribute filter = context.GetArgument("LoginCheckFilter") as LoginCheckFilterAttribute;
            if (filter != null && filter.IsCheck && filter.CheckPermission != null)
            {
                string lowerPath = request.Path.ToString().ToLower();
                bool isSave = lowerPath.IndexOf("/dosave") > -1;
                bool isDel = lowerPath.IndexOf("/dodelete") > -1;
                if (isSave) context.SetArgument("permission-ext", "-Save");
                else if (isDel) context.SetArgument("permission-ext", "-Delete");
                if (isSave || isDel)
                {
                    QQZiFramework.Mvc.IQQZiController controller = filterContext.Controller as QQZiFramework.Mvc.QQZiController;
                    if (controller != null)
                    {
                        string permission = controller.GetParamValue("permission", 0, false, true);
                        //if (permission == null) throw new ClientException("permission不能为空");
                        permission += context.GetArgument("permission-ext");
                        if (context.LoginUser == null) throw new NotLoginException();
                        Permission per = context.GetBusiness<MembershipBLL>().FindPermisson(context.LoginUser.UserId, permission, GetTokenInfo(context).PlatfromId);
                        if (per == null)
                        {
                            //这里不抛出异常，有些页面可以不配置dosave和dodelete，如果这样就不记日志
                            return;
                        }
                        Alias = per.Title;
                        if (isSave)
                        {
                            requestContent = controller.GetEditEntity();
                        }
                        else
                        {
                            string primaryID = request.Query["primaryID"];
                            if (primaryID == null) primaryID = request.Form["primaryID"];
                            if (string.IsNullOrEmpty(primaryID)) throw new ClientException("删除失败，主键primaryID不能为空");
                            requestContent = primaryID;
                        }
                    }
                }
            }
            //记录有取别名的action的访问记录
            if (context.LoginUser != null && Alias != null && requestContent != null)
            {
                TokenInfo tokenInfo = GetTokenInfo(context);
                UserActionLog log = new UserActionLog() { PlatformId = (int)tokenInfo.PlatfromId, SessionId = tokenInfo.Token, UserId = context.LoginUser.UserId, UserAgent = request.Headers["User-Agent"], Ip = ip, CreateTime = DateTime.Now, Url = pathAndQuery, ModuleName = Alias };
                log.Status = 0;
                if (requestContent.Length > 1024) log.Data = "长内容";
                else log.Data = requestContent;
                context.DoSave(log);
                context.SetArgument("system-actionlog", log);
            }
        }

        public virtual void OnActionExecuted(DBContext context, ActionExecutedContext filterContext, string alias)
        {
            UserActionLog log = context.GetArgument("system-actionlog") as UserActionLog;
            if (log != null)
            {
                log.Status = 1;
                log.Message = context.GetArgument("actionlog-msg") as string;
                context.Update(log, "Status,Message");
                context.Close();
            }
        }


        /// <summary>
        /// 获取登录用户信息
        /// </summary> 
        public override BaseUser GetUserFrom(DBContext context)
        {
            HttpContext httpContext = context.GetArgument<Microsoft.AspNetCore.Http.HttpContext>("HttpContext");
            if (httpContext == null) return null;
            //HttpContext httpContext = context.GetHttpContext();
            SqlLogMode logModeTemp = SqlLogMode.NoLog;
            if (context == null) context = NoLogDbContext;
            else
            {
                logModeTemp = context.LogSql;
                context.LogSql = SqlLogMode.NoLog; //在此过程中不记录日志,因为日志会取当前用户,死循环,注意中间不能直接return,要恢复context.LogSql
            }
            BaseUser loginUser = null;
            LoginUserStateType stateType = IsTokenMode(context) ? LoginUserStateType.Redis : context.Membership.UserStateType;
            switch (stateType)
            {

                case LoginUserStateType.Redis:
                    {
                        //验证app请求
                        TokenInfoSimple tokenInfo = GetTokenInfo(context);
                        if (tokenInfo != null)
                        {
                            loginUser = GetRedisUser(tokenInfo.UserId, context);
                        }
                        break;
                    }
                case LoginUserStateType.Session:
                    //loginUser = QQZiFramework.Mvc.Extensions.HttpContext.Current.Session["userinfo"] as BaseUser;
                    break;
                default:
                    {

                    }
                    break;
            }
            if (logModeTemp != SqlLogMode.NoLog) context.LogSql = logModeTemp;
            return loginUser;
        }

       

        /// <summary>
        /// 是否移动端（app，微信，手机浏览器）
        /// </summary>
        public static bool IsMobileDevice(HttpRequest request)
        {
            if (request == null) return true;
            string UserAgent = request.Headers["User-Agent"];
            if (UserAgent == null) return true;
            if (UserAgent.IndexOf("weex", StringComparison.OrdinalIgnoreCase) > -1) return true;
            if (UserAgent.IndexOf("Android", StringComparison.OrdinalIgnoreCase) > -1) return true;
            if (UserAgent.IndexOf("Html5Plus", StringComparison.OrdinalIgnoreCase) > -1) return true;
            if (UserAgent.IndexOf("MicroMessenger", StringComparison.OrdinalIgnoreCase) > -1) return true;
            return false;
        }

        /// <summary>
        /// 是否是ajax访问（包括app访问）
        /// </summary>
        /// <param name="helper"></param>
        /// <returns></returns>
        public static bool IsAjax(DBContext context)
        {
            return IsAjax(context.GetHttpContext().Request);
        }

        /// <summary>
        /// 是否是ajax访问（包括app访问）
        /// </summary>
        /// <param name="helper"></param>
        /// <returns></returns>
        public static bool IsAjax(Microsoft.AspNetCore.Http.HttpRequest request)
        {
            if (request.ContentType != null && request.ContentType.IndexOf("application/json", StringComparison.OrdinalIgnoreCase) > -1) return true;
            string requestedWith = request.Headers["X-Requested-With"];
            bool isAjax = false;
            if (!string.IsNullOrEmpty(requestedWith))
            {
                isAjax = (requestedWith == "XMLHttpRequest" || requestedWith.IndexOf("io.dcloud") > -1);
            }
            if (!isAjax)
            {
                if (requestedWith == null && request.Headers["Access-Control-Request-Headers"] == "x-requested-with")
                {
                    //Options访问
                    isAjax = true;
                }
                else if (IsApp(request, true) || !string.IsNullOrEmpty(request.Query[WebHostMemberShip.APP_TOKEN_NAME]))
                {
                    isAjax = true; //如果没有X-Requested-With，判断是app就用JsonMessage
                }
            }
            return isAjax;
        }

        public static bool IsApp(Microsoft.AspNetCore.Http.HttpRequest request, bool ignoreUrlapp = false)
        {
            if (!ignoreUrlapp && request.Query["app"] == "1") return true;
            string userAgent = request.Headers["User-Agent"];
            if (userAgent == null) return false;
            if (System.Text.RegularExpressions.Regex.IsMatch(userAgent, "Weex/|core/|Html5Plus|okhttp/")) return true;
            return false;
        }

        // /// <summary>
        // /// 是否移动端（app，微信，手机浏览器）
        // /// </summary>
        // public static bool IsMobileDevice(System.Web.HttpRequestBase request)
        // {
        //     if (request == null) return true;
        //     if (request.Browser == null || request.UserAgent == null) return true;
        //     if (request.Browser.IsMobileDevice) return true;
        //     if (request.Params["HTTP_APP"] == "1") return true;
        //     Regex regex = new Regex("okhttp|weex|Android|Html5Plus|MicroMessenger", RegexOptions.IgnoreCase);
        //     if (regex.IsMatch(request.UserAgent)) return true;
        //     //if (request.UserAgent.IndexOf("weex", StringComparison.OrdinalIgnoreCase) > -1) return true;
        //     //if (request.UserAgent.IndexOf("Android", StringComparison.OrdinalIgnoreCase) > -1) return true;
        //     //if (request.UserAgent.IndexOf("Html5Plus", StringComparison.OrdinalIgnoreCase) > -1) return true;
        //     //if (request.UserAgent.IndexOf("MicroMessenger", StringComparison.OrdinalIgnoreCase) > -1) return true;
        //     return false;
        // }
        protected int GetLoginStateDBIndex(DBContext context)
        {

            return context.GetSettingValue<int>("Redis:Login", false, DBContext.Default_Redis_Database_Index);

        }


        /// <summary>
        /// 保存用户信息到cookie或者session
        /// </summary>
        /// <param name="userInfo">用户信息</param>
        /// <param name="Expires">超时时间</param>
        /// <returns>TokenInfo,0:返回Token供客户端（比如app），1：appSecret</returns>
        public override TokenInfo SetUserLoginState(BaseUser userInfo, LoginUserStateType userStateType, DateTime Expires, LoginPlatfromId platForm, object extValues, DBContext context)
        {
            userInfo.LastLoginTime = DateTime.Now;
            if (userInfo == null) throw new ClientException("RecordLogin exception , userinfo is null");
            string appSecret = Guid.NewGuid().ToString();
            TokenInfo tokenInfo = new TokenInfo { PlatfromId = platForm, AppSecret = appSecret, Values = extValues, UserId = userInfo.UserId };
            tokenInfo.ExpiresAt = Expires.ToString("yyyy-MM-dd HH:mm:ss");
            switch (userStateType)
            {
                case LoginUserStateType.Session:
                    //QQZiFramework.Mvc.Extensions.HttpContext.Current.Session["userinfo"] = userInfo;
                    break;

                case LoginUserStateType.Redis:
                    tokenInfo.Token = Utility.EncryptMD5(userInfo.UserId + "_" + userInfo.LastLoginTime.ToString("yyyyMMddHHmmss")) + Utility.EncryptNumber(userInfo.UserId);
                    string redisVal = Newtonsoft.Json.JsonConvert.SerializeObject(tokenInfo);
                    int dbIndex = GetLoginStateDBIndex(context);
                    context.GetRedisDatabase(dbIndex).SetRedisItem("login_" + tokenInfo.Token, redisVal, Expires);
                    break;
                default:
                    // HttpCookie cookie = new HttpCookie("userinfo");
                    // var jSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore };
                    // cookie.Values["json"] = context.Membership.UserToCookie(userInfo);
                    // cookie.Values["token"] = token;
                    // if (context.LoginTokenInfo == null && ColysSharpControllerBase.GetAppSetting<bool>("SessionExpire", ' ', false) == true)
                    // {
                    //     context.SetRedisItem("admin_login_" + userInfo.UserId, token);
                    //     QQZiFramework.Mvc.Extensions.HttpContext.Current.Session["LoginTime"] = userInfo.LastLoginTime;
                    // }
                    // cookie.Expires = Expires;
                    // //#if DEBUG
                    // //cookie.Expires = DateTime.MaxValue;
                    // //#endif
                    // QQZiFramework.Mvc.Extensions.HttpContext.Current.Response.Cookies.Add(cookie);
                    break;
            }
            return tokenInfo;
        }



        public override string GetRequestHeader(DBContext context, string name)
        {
            HttpContext httpContext = context.GetHttpContext();
            //QQZiFramework.Mvc.Extensions.HttpContext.Current.Request.UserAgent
            string val = httpContext.Request.Headers["name"];
            if (val == null)
            {
                val = httpContext.Request.Headers["User-Agent"];
            }
            return val;
        }
        public virtual string GetRequestToken(DBContext context)
        {
            HttpContext httpContext = context.GetHttpContext();
            if (httpContext == null) return null;
            if (httpContext.WebSockets != null && httpContext.WebSockets.IsWebSocketRequest)
            {
                string[] arr = httpContext.Request.Path.ToString().Split('/');
                return arr[arr.Length - 1];
            }
            else
            {
                string token = httpContext.Request.Query[APP_TOKEN_NAME];
                if (string.IsNullOrEmpty(token)) return null;
                return token; // Utility.Decrypt(token);
            }

        }

        /// <summary>
        /// get user token and appRedis
        /// </summary>
        /// <returns></returns>
        public override TokenInfo GetTokenInfo(DBContext context)
        {
            TokenInfo tokenInfo = context.GetArgument<TokenInfo>("__TokenInfo__");
            if (tokenInfo != null) return tokenInfo;
            string token = GetRequestToken(context);
            if (token == null) return null;
            string key = "login_" + token;
            string json = context.GetRedisDatabase(GetLoginStateDBIndex(context)).GetRedisItem<string>(key, false);
            if (json == null) return null;
            JToken jToken = Newtonsoft.Json.Linq.JToken.Parse(json);
            tokenInfo = new TokenInfo();
            tokenInfo.ExpiresAt = jToken.Value<string>("ExpiresAt");
            tokenInfo.Token = jToken.Value<string>("Token");
            int platform = jToken.Value<int>("PlatfromId");
            if (platform == 0) platform = 1;
            tokenInfo.PlatfromId = (LoginPlatfromId)platform;
            tokenInfo.UserId = jToken.Value<int>("UserId");
            tokenInfo.AppSecret = jToken.Value<string>("AppSecret");
            tokenInfo.ValueTypeName = jToken.Value<string>("ValueTypeName");
            if (jToken["Values"].HasValues && tokenInfo.ValueTypeName != null)
            {
                tokenInfo.Values = jToken["Values"].ToObject(Type.GetType(tokenInfo.ValueTypeName));
            }
            context.SetArgument("__TokenInfo__", tokenInfo);
            return tokenInfo;
        }



        public override bool IsDevelopment()
        {
            return QQZiFramework.Mvc.Extension.Hosting.IsDevelopment();
        }

        public override T GetSettingValue<T>(DBContext context, string path, bool throwNoFoundError = false, T defaultVal = default(T))
        {
            string s = Extension.Configuration[path];
            if (s == null) return defaultVal;
            else return (T)Convert.ChangeType(s, typeof(T));
        }

        public override void ClearCache(DBContext context)
        {
            queryMapping = null;
        }

        /// <summary>
        /// 是否转繁体
        /// </summary>
        public virtual bool ResponseTraditional
        {
            get { return false; }
        }

        private static ILoggerRepository repository;

        protected virtual ILoggerRepository GetLogRepository()
        {
            if (repository != null) return repository;
            string logConfigPath = System.IO.Path.Combine(QQZiFramework.Mvc.Extension.GetAppRootPath(), "log4net.config");
            if (!File.Exists(logConfigPath))
            {
                string oldPath = System.IO.Path.Combine(QQZiFramework.Mvc.Extension.GetWWWRootPath(), "log4net.config");
                if (!File.Exists(oldPath)) throw new FileNotFoundException(logConfigPath);
                else File.Move(oldPath, logConfigPath);
            }
            FileInfo logFile = new FileInfo(logConfigPath);
            repository = LogManager.CreateRepository("NETCoreRepository");
            log4net.Config.XmlConfigurator.Configure(repository, logFile);

            return repository;
        }

        // static Queue<LogEvent> MessageQueue = new Queue<LogEvent>();
        // static System.Threading.Timer timer;


        /// <summary>
        /// 日志记录
        /// </summary>       
        public override void LogMessage(string message, string moduleName, DBContext context)
        {
            log4net.ILog loger = log4net.LogManager.GetLogger(GetLogRepository().Name, moduleName == null ? "system" : moduleName);
            loger.Info(message);
        }

        /// <summary>
        /// 异常日志记录
        /// </summary>  
        public override void LogException(Exception ex, string moduleName, DBContext context)
        {
            log4net.ILog loger = log4net.LogManager.GetLogger(GetLogRepository().Name, moduleName == null ? "system" : moduleName);
            loger.Error(ex);
           
        }

        /// <summary>
        /// 记录调试日志
        /// </summary>  
        public override void LogDebug(string message, string moduleName, DBContext context)
        {
            log4net.ILog loger = log4net.LogManager.GetLogger(GetLogRepository().Name, moduleName == null ? "system" : moduleName);
            loger.Debug(message);
        }


        // private static void triggerLogHandle()
        // {
        //     if (timer == null)
        //     {
        //         timer = new System.Threading.Timer(new System.Threading.TimerCallback(SaveEventLogHandle), null, 15000, 0);
        //     }
        // }

        public virtual void SetContextArgs(DBContext context, HttpContext httpContext)
        {

            if (httpContext == null) return; 
            //QQZiFramework.Mvc.Extensions.HttpContext.SetCurrentDBContext(context);
            context.SetArgument("HttpContext", httpContext);
            context.SetArgument("IsMobileDevice", IsMobileDevice(httpContext.Request));
            context.SetArgument("IP", GetWebClientIp(httpContext.Request));
            string wxqrcodeShareId = httpContext.Request.Headers["WX-ShareId"];
            if (!string.IsNullOrEmpty(wxqrcodeShareId)) context.SetArgument("WX-ShareId", wxqrcodeShareId);
            if (!httpContext.Items.ContainsKey(DBCONTEXT_NAME_IN_HTTP_CONTEXT))
            {    
                httpContext.Items.Add(DBCONTEXT_NAME_IN_HTTP_CONTEXT, context);
            }
        }

        /// <summary>
        /// 获取当前请求的DBContext
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        public static DBContext GetCurrentContext(HttpContext httpContext)
        {
            if (!httpContext.Items.ContainsKey(WebHostMemberShip.DBCONTEXT_NAME_IN_HTTP_CONTEXT)) return null;
            return httpContext.Items[WebHostMemberShip.DBCONTEXT_NAME_IN_HTTP_CONTEXT] as DBContext;
        }

        public const string APP_TOKEN_NAME = "qqzitoken";

        /// <summary>
        /// 检测扩展名
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        internal static bool CheckFileExtension(string fileExtension)
        {
            //获取文件后缀

            if (fileExtension != null)
                fileExtension = fileExtension.ToLower();
            else
                return false;

            if (fileExtension != ".jpg" && fileExtension != ".gif" && fileExtension != ".png" && fileExtension != ".jpeg")
                return false;

            return true;
        }

         
    }


}